/***
 * 条件变量的正确使用方法
 * P334-335
 */

#include <pthread.h>

struct msg
{
    struct msg *m_next;
    /* ... more stuff here ... */
};

struct msg *workq; //工作队列的 队列头指针

pthread_cond_t qready = PTHREAD_COND_INITIALIZER; // 全局的 static的 条件变量

pthread_mutex_t qlock = PTHREAD_MUTEX_INITIALIZER; // 全局的 static的 互斥量

//--------------------------生产者 消费者 模型---------------------------------//

// 消费者
void process_msg()
{
    struct msg *mp;

    for (;;)
    {
        pthread_mutex_lock(&qlock);
        while (workq == NULL) // 队头指针为NULL,说明任务队列为空
            pthread_cond_wait(&qready, &qlock);
        /*
                1. thread wait on qready
                2. unlock qlock
                ....生产者 生产出来了一个 可以消费了  此时通过qready感知到
                3. relock qlock before return
            */

        mp = workq;         // 从队列头拿出来一个
        workq = mp->m_next; // 队列头 下移一下

        pthread_mutex_unlock(&qlock);
        /* now process the message mp */
    }
}

// 生产者
void enqueue_msg(struct msg *mp)
{
    pthread_mutex_lock(&qlock);

    // 头插法: 将每个object的指针 每次都插到 队头
    mp->m_next = workq; // 指向 队头指针
    workq = mp;         // 队头指针 指向传进来的object的指针

    pthread_mutex_unlock(&qlock);

    pthread_cond_signal(&qready); // 通过 条件变量 唤醒一个等待着的线程
}
